/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
//
//
*/

#ifndef __UMC_AVS_PIC_H
#define __UMC_AVS_PIC_H

#include "ippdefs.h"
#include "umc_structures.h"

#include "umc_avs_sequence_header.h"
#include "umc_avs_picture_header.h"
#include "umc_avs_slice.h"
#include "umc_avs_memory_piece.h"
#include "umc_avs_list.h"
#include "umc_avs_context.h"
#include "umc_avs_consts.h"

#include "vm_mutex.h"

namespace UMC
{

// forward declaration of used types
struct AVS_MB_INFO;
class MeFrame;

class AVSPicture
{
public:
    // Default constructor
    AVSPicture(void);
    // Destructor
    virtual
    ~AVSPicture(void);

    // Initialize the object
    virtual
    Status Init(void);

    // Release the object
    virtual
    void Close(void);

    // Set planes to object
    void ResetPicture(AVS_SEQUENCE_HEADER *pSeqHeader,
                      void **pPlanes,
                      Ipp32s iPitch,
                      eAVSPicStructure picStructure);

    // Assign video plane pointers to a slice
    virtual
    void AssignVideoPlanes(AVSSlice *pSlice);

    // Move given slice to the exhausted queue
    void MarkSliceAsDone(AVSSlice *pSlice);

    AVS_PICTURE_HEADER m_picHeader;                             // (AVS_PICTURE_HEADER) picture's header

    AVS_MB_INFO *m_pMbInfo;                                     // (AVS_MB_INFO *) frame's array of macro blocks info structures

    union
    {
    Ipp8u *(m_pPlanes8u[3]);                                    // (Ipp8u *([])) array of pointers to picture's planes
    Ipp16u *(m_pPlanes16u[3]);                                  // (Ipp16u *([])) array of pointers to picture's planes
    };
    union
    {
    const Ipp8u *(m_pSrcPlanes8u[3]);                           // (const Ipp8u *([])) array of pointers to picture's source planes
    const Ipp16u *(m_pSrcPlanes16u[3]);                         // (const Ipp16u *([])) array of pointers to picture's source planes
    };
    Ipp32s m_iPitch;                                            // (Ipp32s) pitch of planes

    ColorFormat m_colorFormat;                                  // (ColorFormat) color format of the current picture

    IppiSize m_sizeLuma;                                        // (IppiSize) dimension of the luminance plane
    IppiSize m_sizeChroma;                                      // (IppiSize) dimension of the chrominance plane

    eAVSPicStructure m_picStructure;                            // (eAVSPicStructure) structure of this picture

    AVSPicture *(m_pRefs[AVS_DIRECTIONS][4]);                   // (AVSPicture *([])) array of pointers to reference frames
    Ipp32s m_blockDist[AVS_DIRECTIONS][4];                      // (Ipp32s [][]) block distances, depending on ref index
    Ipp32s m_distIdx[AVS_DIRECTIONS][4];                        // (Ipp32s [][]) distance indecies of reference pictures

    AVSList<AVSSlice> m_Slices;                                 // (AVSList<AVSSlice>) initialized slice queue
    AVSList<AVSSlice> m_SlicesSpent;                            // (AVSList<AVSSlice>) exhausted slice queue

    MeFrame *m_pMeFrame;                                        // (MeFrame *) pointer to ME frame
};

class AVSFrame : public AVSPicture
{
public:
    // Default constructor
    AVSFrame(void);
    // Destructor
    virtual
    ~AVSFrame(void);

    // Initialize the object
    virtual
    Status Init(void);
    // Set planes pointers to slices,
    // distribute them to field.
    Status SetSlices(void);

    // Is the frame decompressed
    bool IsReady(void);

    // Has the frame been shown
    inline
    bool IsShown(void);
    // Set the frame into the shown state
    inline
    void SetShown(void);

    // Is the frame a reference frame
    inline
    bool IsReference(void);

    // Reset all frames counters and flags
    void Reset(void);

    // Assign video plane pointers to a slice
    virtual
    void AssignVideoPlanes(AVSSlice *pSlice);

    // Get the allocated buffer size
    inline
    size_t GetBufferSize(void);

    // Obtain pointer to a frame (field)
    inline
    AVSPicture *GetPicture(eAVSPicStructure picStructure);

    // Reset frame's references
    void SetReferences(AVSFrame **pRefs);

    // Remove all slices into the given list
    void RemoveSlices(AVSList<AVSSlice> *pList);

    // Remove all memoryPieces into the given list
    void RemoveMemoryPieces(AVSList<AVSMemory> *pList);

    // Set PTS to the picture
    inline
    void SetTime(Ipp64f dPicTime);
    // Get PTS of the picture
    inline
    Ipp64f GetTime(void);

    // Are reference frame set for the frame
    inline
    bool ReferencesReady(void);

    AVS_SEQUENCE_HEADER m_seqHeader;                            // (AVS_SEQUENCE_HEADER) sequence's header

    AVS_COLOR_CONVERTING_CONTEXT m_cnvCtx;                      // (AVS_COLOR_CONVERTING_CONTEXT) conversion's parameters
    AVS_COPY_CONTEXT m_cpyCtx;                                  // (AVS_COPY_CONTEXT) context to copy encoded frame

    AVSList<AVSMemory> m_MemoryPieces;                          // (AVSList<AVSMemory>) associated memory pieces

    Ipp32u m_frameNum;                                          // (Ipp32u) frame number

protected:
    // Release the object
    void Close(void);

    AVSPicture m_Fields[2];                                     // (AVSPicture) fields structures of the frame

    Ipp32s m_iShown;                                            // (Ipp32s) how many times the frame was shown

    void *m_pvVideoPlane;                                       // (void *) pointer to allocated video plane
    size_t m_bufSize;                                           // (size_t) size of allocated video plane buffer

    IppiSize m_dimLumaAllocated;                                // (IppiSize) size of allocated luminance plane
    IppiSize m_dimChromaAllocated;                              // (IppiSize) size of allocated chrominance plane
    IppiSize m_dimMBAllocated;                                  // (IppiSize) amount of allocated macroblock info structures

    Ipp64f m_dPicTime;                                          // (Ipp64f) PTS of the picture
};

//
// Inline functions
//

inline
bool AVSFrame::IsShown(void)
{
    return (0 != m_iShown);

} // bool AVSFrame::IsShown(void)

inline
void AVSFrame::SetShown(void)
{
    m_iShown = 1;

} // void AVSFrame::SetShown(void)

inline
bool AVSFrame::IsReference(void)
{
    return (AVS_B_PICTURE != m_picHeader.PictureType);

} // bool AVSFrame::IsReference(void)

inline
size_t AVSFrame::GetBufferSize(void)
{
    size_t nSize = m_iPitch * m_sizeLuma.height;

    switch (m_colorFormat)
    {
    case YUV420:
        nSize = (nSize * 3) / 2;
        break;

    case YUV422:
        nSize = nSize * 2;
        break;

    case YUV444:
        nSize = nSize * 3;
        break;

    default:
        break;
    };

    return nSize;

} // size_t AVSFrame::GetBufferSize(void)

inline
AVSPicture *AVSFrame::GetPicture(eAVSPicStructure picStructure)
{
    AVSPicture *pToReturn;

    switch (picStructure)
    {
    case AVS_UPPER_FIELD:
        pToReturn = m_Fields + 0;
        break;

    case AVS_LOWER_FIELD:
        pToReturn = m_Fields + 1;
        break;

    default:
        pToReturn = this;
        break;
    }

    return pToReturn;

} // AVSPicture *AVSFrame::GetReferencePicture(eAVSPicStructure refType)

inline
void AVSFrame::SetTime(Ipp64f dPicTime)
{
    m_dPicTime = dPicTime;

} // void AVSFrame::SetTime(Ipp64f dPicTime)

inline
Ipp64f AVSFrame::GetTime(void)
{
    return m_dPicTime;

} // Ipp64f AVSFrame::GetTime(void)

inline
bool AVSFrame::ReferencesReady(void)
{
    if (AVS_B_PICTURE == m_picHeader.PictureType)
    {
        if (m_pRefs[AVS_FORWARD][0])
            return true;
        else
            return false;
    }
    else
        return true;

} // bool AVSFrame::ReferencesReady(void)

template <class sampleType> inline
void GetPlanesPointers(const sampleType **pDstPlanes,
                       const sampleType **pSrcPlanes,
                       size_t planeStep,
                       Ipp32u MbY,
                       ColorFormat colorFormat)
{
    // advance luminance plane
    pDstPlanes[0] = pSrcPlanes[0] + MbY * 16 * planeStep;

    // advance chrominance planes
    switch (colorFormat)
    {
    case YUV420:
        pDstPlanes[1] = pSrcPlanes[1] + MbY * 8 * planeStep;
        pDstPlanes[2] = pSrcPlanes[2] + MbY * 8 * planeStep;
        break;

    default:
        pDstPlanes[1] = pSrcPlanes[1] + MbY * 16 * planeStep;
        pDstPlanes[2] = pSrcPlanes[2] + MbY * 16 * planeStep;
        break;
    }

} // void GetPlanesPointers(sampleType **pDstPlanes,

// Get readness of picture's structures used in decoding
Ipp32s GetDecReadyLevel(AVSPicture *pPic);

// Get readness of picture's planes used in reconstruction
Ipp32s GetRecReadyLevel(AVSPicture *pPic);

} // namespace UMC

#endif // __UMC_AVS_PIC_H
